#pragma once

#include "BasicObject.h"
#include "typdefs.h"
#include "emotionalmemory.h"
#include <map>
#include "agent.h"
#include "emotion.h"
#include "Value.h"
#include "goal.h"

namespace BAA
{

	class Role;
	typedef std::map< Role*,  Role*, std::less< Role*>>		RoleRoleMap;

	class Agent;
	typedef std::vector< Agent*>									AgentVector;
	typedef std::map< Agent*, Agent*, std::less< Agent*>>			AgentPointerMap;
	typedef std::map< int,  Agent*, std::less<int>>					AgentIDMap;
	typedef std::map<std::string, Agent*, std::less< std::string>>			AgentNameMap;

	class Value;
	typedef std::map< Value*, Value*, std::less< Value*>>			ValueValueMap;
	typedef std::map<std::string, std::vector<Value*>, std::less<std::string>>		StringValuesMap;
	typedef std::map< Agent*, std::vector<Value*>*, std::less< Agent*>>	AgentValuesMap;


	class Goal;
	typedef std::map<std::string, Goal*>									StringGoalMap;
	typedef std::map<Agent*, std::vector<Goal*>>							AgentGoalsMap;


	class Action;
	typedef std::map<std::string, Action*>								StringActionMap;


	class Emotion;
	typedef std::map<const std::string, Emotion*>								StringEmotionMap;

	class EmotionalMemory;

	class Role:public BasicObject
	{
	public:
		Role(const std::string name):BasicObject(name)
		{

		}

		~Role()
		{
			

		}

		virtual void Create()=0;
		virtual void Initialize(Agent * self, AgentPointerMap* targets, float roleImportance);

		Agent * Self() const { return mSelf; }
		void Self(Agent * val) { mSelf = val; }

		BAA::AgentPointerMap* Targets() { return mTargets; }
		const BAA::AgentPointerMap* Targets() const { return mTargets; }
		void Targets(BAA::AgentPointerMap* val) { mTargets = val; }

		BAA::ValueValueMap* Values() { return &mValues; }
		const BAA::ValueValueMap Values() const{ return mValues; }
		void Values(BAA::ValueValueMap val) { mValues = val; }

		BAA::StringFloatMap* StringFloatProperties() { return &mStringFloatProperties; }
		void StringFloatProperties(BAA::StringFloatMap val) { mStringFloatProperties = val; }

		BAA::StringEmotionMap* Emotions() { return &mEmotions; }
		void Emotions(BAA::StringEmotionMap val) { mEmotions = val; }

		float RoleImportance() { return mRoleImportance; }
		void RoleImportance(float val) { mRoleImportance = val; }

		std::vector<BAA::EmotionalMemory*> * GetEmotionalMemories()  { return &mEmotionalMemories; }
		//vector<BAA::EmotionalMemory*> * GetEmotionalMemory()  const{ return &mEmotionalMemory; }
		void AddEmotionalMemory(BAA::EmotionalMemory* val) { mEmotionalMemories.push_back(val); }

		StringGoalMap * Goals() { return &mGoals; }
		void Goals(StringGoalMap  val) { mGoals = val; }


		StringActionMap * Actions() { return &mActions; }
		void Actions(StringActionMap  val) { mActions = val; }


		Agent* TargetContainsAgent(Agent * agent);
		Agent* TargetContainsAgent(AgentPointerMap * agents);

		void CompressEmotionalMemory()
		{
			// reduce in size, only take most important memories
			// add weight based on their importance
			
		}

	protected:


		float				mRoleImportance;		 // importance of role
 
		Agent *				mSelf;					 // who agent is with this role

		AgentPointerMap *	mTargets;				 // who the role is directed at

		std::vector<EmotionalMemory*> mEmotionalMemories; // Any emotional memories associated with this role.

		StringEmotionMap	mEmotions;   // Any emotions specific to this role

		ValueValueMap 		mValues;                 // Values within this role

		StringGoalMap       mGoals;                  // Goals of the role

		StringActionMap 	mActions;				// An map of the actions the role can perform

		StringFloatMap 		mStringFloatProperties;  // any properties relevant to the role
 
	
	};// end class

}// end namespace
